package com.example.maze.model;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.List;

/**
 * 迷宫类，表示整个迷宫结构
 * 
 * @author maze-demo
 */
public class Maze {
    private static final Logger logger = LoggerFactory.getLogger(Maze.class);

    private final int rows;
    private final int cols;
    private final Cell[][] grid;
    private Coordinate start;
    private Coordinate end;

    public Maze(int rows, int cols) {
        if (rows <= 0 || cols <= 0) {
            throw new IllegalArgumentException("迷宫尺寸必须为正数");
        }
        
        this.rows = rows;
        this.cols = cols;
        this.grid = new Cell[rows][cols];
        
        // 初始化所有单元格为墙
        initializeGrid();
        
        logger.debug("创建了 {}x{} 的迷宫", rows, cols);
    }

    /**
     * 初始化网格，所有单元格默认为墙
     */
    private void initializeGrid() {
        for (int row = 0; row < rows; row++) {
            for (int col = 0; col < cols; col++) {
                grid[row][col] = new Cell(row, col, Cell.Type.WALL);
            }
        }
    }

    /**
     * 获取指定坐标的单元格
     */
    public Cell getCell(int row, int col) {
        if (!isValidCoordinate(row, col)) {
            throw new IndexOutOfBoundsException(
                String.format("坐标 (%d,%d) 超出迷宫范围 (%d,%d)", row, col, rows, cols));
        }
        return grid[row][col];
    }

    public Cell getCell(Coordinate coord) {
        return getCell(coord.getRow(), coord.getCol());
    }

    /**
     * 设置单元格类型
     */
    public void setCell(int row, int col, Cell.Type type) {
        getCell(row, col).setType(type);
    }

    public void setCell(Coordinate coord, Cell.Type type) {
        setCell(coord.getRow(), coord.getCol(), type);
    }

    /**
     * 检查坐标是否有效
     */
    public boolean isValidCoordinate(int row, int col) {
        return row >= 0 && row < rows && col >= 0 && col < cols;
    }

    public boolean isValidCoordinate(Coordinate coord) {
        return isValidCoordinate(coord.getRow(), coord.getCol());
    }

    /**
     * 获取指定单元格的可通行邻居
     */
    public List<Cell> getPassableNeighbors(Cell cell) {
        List<Cell> neighbors = new ArrayList<>();
        Coordinate[] neighborCoords = cell.getCoordinate().getNeighbors();
        
        for (Coordinate coord : neighborCoords) {
            if (isValidCoordinate(coord)) {
                Cell neighbor = getCell(coord);
                if (neighbor.isPassable()) {
                    neighbors.add(neighbor);
                }
            }
        }
        
        return neighbors;
    }

    /**
     * 获取所有邻居单元格（包括墙）
     */
    public List<Cell> getAllNeighbors(Cell cell) {
        List<Cell> neighbors = new ArrayList<>();
        Coordinate[] neighborCoords = cell.getCoordinate().getNeighbors();
        
        for (Coordinate coord : neighborCoords) {
            if (isValidCoordinate(coord)) {
                neighbors.add(getCell(coord));
            }
        }
        
        return neighbors;
    }

    /**
     * 设置起点
     */
    public void setStart(int row, int col) {
        // 清除之前的起点
        if (start != null) {
            setCell(start, Cell.Type.PATH);
        }
        
        start = new Coordinate(row, col);
        setCell(start, Cell.Type.START);
        logger.debug("设置起点: {}", start);
    }

    public void setStart(Coordinate coord) {
        setStart(coord.getRow(), coord.getCol());
    }

    /**
     * 设置终点
     */
    public void setEnd(int row, int col) {
        // 清除之前的终点
        if (end != null) {
            setCell(end, Cell.Type.PATH);
        }
        
        end = new Coordinate(row, col);
        setCell(end, Cell.Type.END);
        logger.debug("设置终点: {}", end);
    }

    public void setEnd(Coordinate coord) {
        setEnd(coord.getRow(), coord.getCol());
    }

    /**
     * 重置迷宫状态（清除寻路痕迹）
     */
    public void reset() {
        for (int row = 0; row < rows; row++) {
            for (int col = 0; col < cols; col++) {
                grid[row][col].reset();
            }
        }
        
        // 重新设置起点和终点
        if (start != null) {
            setCell(start, Cell.Type.START);
        }
        if (end != null) {
            setCell(end, Cell.Type.END);
        }
        
        logger.debug("重置迷宫状态");
    }

    /**
     * 检查迷宫是否有效（有起点和终点）
     */
    public boolean isValid() {
        return start != null && end != null;
    }

    /**
     * 获取所有指定类型的单元格
     */
    public List<Cell> getCellsOfType(Cell.Type type) {
        List<Cell> cells = new ArrayList<>();
        for (int row = 0; row < rows; row++) {
            for (int col = 0; col < cols; col++) {
                if (grid[row][col].getType() == type) {
                    cells.add(grid[row][col]);
                }
            }
        }
        return cells;
    }

    // Getters
    public int getRows() {
        return rows;
    }

    public int getCols() {
        return cols;
    }

    public Coordinate getStart() {
        return start;
    }

    public Coordinate getEnd() {
        return end;
    }

    public Cell getStartCell() {
        return start != null ? getCell(start) : null;
    }

    public Cell getEndCell() {
        return end != null ? getCell(end) : null;
    }

    @Override
    public String toString() {
        return String.format("Maze[%dx%d, start=%s, end=%s]", rows, cols, start, end);
    }
}